<script>
import { getRoleListAPI, addRoleAPI, deleteRoleAPI, updateRoleAPI, assignPremAPI } from '@/api/roleApi'
import PermissionList from '@/views/role/components/permissionList.vue'

export default {
  name: 'Role',
  components: { PermissionList },
  data() {
    const validaName = (rule, value, callback) => {
      const isExist = this.roleList.every(item => item.name !== value)
      if (!isExist) return callback(new Error('输入的角色名称已经存在'))
      callback()
    }
    return {
      /* 分页的参数 */
      pageParams: {
        page: 1,
        pagesize: 10,
        total: 0
      },
      /* 添加角色的表单数据对象 */
      roleForm: {
        // 角色的名称
        name: '',
        // 角色的描述
        description: '',
        // 是否启用角色 1启用 0关闭
        state: 1
      },
      /* 添加角色的表单校验对象 */
      roleRules: {
        name: [
          { required: true, trigger: 'blur', message: '请输入角色名称' },
          { validator: validaName, trigger: 'blur' }
        ],
        description: [
          { required: true, trigger: 'blur', message: '请输入角色描述' }
        ]
      },
      /* 角色列表 */
      roleList: [],
      /* 是否显示添加角色的弹层 */
      showRoleDialog: false,
      /* 是否显示添加权限的弹框 */
      isShowPermission: false
    }
  },
  methods: {
    assignPremAPI,
    /* 获取角色列表的请求函数 */
    async fetchRoleList() {
      try {
        // 调用getRoleListAPI(this.pageParams)接口函数传入分页参数获取当前页的角色列表
        const { data: roleResult } = await getRoleListAPI(this.pageParams)
        // 为每个角色对象添加isEdit字段默认为false以及定义一个editRow没每个role
        roleResult.rows.forEach(item => {
          item.isEdit = false
          item.editRow = { name: item.name, state: item.state, description: item.description, id: item.id }
        })
        // 赋值total
        this.pageParams.total = roleResult.total
        // 赋值角色列表
        this.roleList = roleResult.rows
      } catch (e) {
        // 角色列表获取失败
        this.$message.error(e.message)
      }
    },
    /* 当前分页展示的数据条数发生变化的回调函数 */
    handleSizeChange(size) {
      // 赋值size
      this.pageParams.pagesize = size
      // 调用fetchRoleList()重新发送请求获取角色列表
      this.fetchRoleList()
    },
    /* 当前分页页码发生变化的回调函数 */
    handleCurrentChange(page) {
      // 赋值page
      this.pageParams.page = page
      // 调用fetchRoleList()重新发送请求获取角色列表
      this.fetchRoleList()
    },
    /* 点击添加角色按钮的回调函数(打开弹层让用户添加角色) */
    handleAddRole() {
      this.showRoleDialog = true
    },
    /* 添加角色时点击确定按钮的回调函数(发送添加角色的请求添加一个角色) */
    async handleSubmit() {
      //对整个表单进行校验的方法，参数为一个回调函数。该回调函数会在校验结束后被调用，并传入两个参数：是否校验成功和未通过校验的字段。若不传入回调函数，则会返回一个 promise
      const valid = await this.$refs.roleForm.validate().catch(e => e)
      // valid为false代表校验失败,valid为true代表校验成功
      if (!valid) return
      try {
        // 调用addRoleAPI(this.roleForm)接口函数传入当前的参数发送请求返回的是一个Promise对象
        const { message } = await addRoleAPI(this.roleForm)
        // 提示用户添加角色成功
        this.$message.success(message)
        if (this.pageParams.total % this.pageParams.pagesize === 0) {
          this.pageParams.total += 1
          this.pageParams.page++
        }
        // 调用fetchRoleList()请求函数重新获取角色列表
        this.fetchRoleList()
        // 关闭弹层
        this.showRoleDialog = false
      } catch (e) {
        // 提示用户添加角色失败
        this.$message.error(e.message)
      }
    },
    /* 添加角色时点击取消按钮的回调函数(关闭弹层) */
    handleCancel() {
      this.showRoleDialog = false
    },
    /* 点击删除角色按钮的回调函数(发送删除一个角色的请求) */
    async handleDeleteRole(role) {
      // 提示用户是否真的要删除，该函数返回一个Promise对象
      const confirm = await this.$confirm(`此操作将永久${role.name}角色, 是否继续?`, '提示', { confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).catch(e => e)
      // 点击了取消则return出去，不执行下面的逻辑
      if (confirm === 'cancel') return
      try {
        // 调用deleteRoleAPI(role.id)传入当前要删除的角色ID，该接口函数返回一个Promise对象
        const { message } = await deleteRoleAPI(role.id)
        // 提示用户删除角色成功
        this.$message.success(message)
        // 如果当前页已经删除的没有数据了则回到前面的一页
        if (this.roleList.length <= 1) this.pageParams.page -= 1
        // 调用fetchRoleList()发送请求重新获取角色列表的数据
        this.fetchRoleList()
      } catch (e) {
        // 提示用户角色删除失败
        this.$message.error(e.message)
      }
    },
    /* 点击编辑角色按钮的回调函数(开启当前行的编辑模式让用户可以对某行的角色详情进行编辑) */
    handleEditRole(role) {
      //   开启当前行的编辑模式
      role.isEdit = true
      // 更新一下editRow
      role.editRow = { name: role.name, id: role.id, state: role.state, description: role.description }
    },
    /* 编辑角色状态下点击更新按钮的回调函数(发送一个编辑角色详情的请求) */
    async handleUpdateRole(role) {
      // 判断输入的角色名称和角色描述是否为空,如果为 空zereturn出去不执行下面的逻辑
      if (role.editRow.name === '' || role.editRow.description === '') return this.$message.warning('输入不能为空')
      try {
        // 调用updateRoleAPI(editRow)接口函数传入当前缓存的角色详情发送更新角色详情的请求,该接口函数返回一个Promise对象
        const { message } = await updateRoleAPI(role.editRow)
        // 提示用户更新角色详情成功
        this.$message.success(message)
        // 调用fetchRoleList()发送请求重新获取角色列表
        // this.fetchRoleList()
        // 更新当前行展示的数据
        Object.assign(role, { ...role.editRow, isEdit: false })
        // 关闭当前行的编辑模式
        role.isEdit = false
      } catch (e) {
        // 跟新角色详情失败
        this.$message.error(e.message)
      }

    },
    /* 编辑角色状态下点击取消按钮的回调函数(关闭当前行的编辑模式) */
    handleUpdateCalcel(role) {
      role.isEdit = false
    },
    /* switch开关的change回调函数(用于开启或者关闭角色) */
    async changeState(row) {
      try {
        /* 整理参数 */
        const role = { ...row, state: row.state === 1 ? 0 : 1 }
        // 调用updateRoleAPI(role)接口函数,传入当前整理好的role参数,该接口函数返回一个Promise对象
        const { message } = await updateRoleAPI(role)
        // 提示用户修改成功
        this.$message.success(message)
        // 调用fetchRoleList()发送请求重新获取角色列表的数据
        this.fetchRoleList()
      } catch (e) {
        // 提示用户修改角色详情失败
        this.$message.error(e.message)
      }
    },
    /* 点击分配权限按钮的回调函数 */
    async handleAssignPrem(role) {
      /* 当添加权限的弹框显示的时候先调用子组件的方法fetchPermission()获取所有的权限列表，然后再调用获取角色详情的请求函数fetchRoleDetail(role.id)获取当前角色下的权限ID数组 */
      await this.$refs.permissionList.fetchRoleDetail(role.id)
      await this.$refs.permissionList.fetchPermission()
      this.isShowPermission = true
    }

  },
  watch: {
    /* 监听showRoleDialog字段的变化调用this.$refs.roleForm.resetFields()函数清空添加角色的表单数据 */
    showRoleDialog(newValue, oldValue) {
      this.$nextTick(() => {
        this.$refs.roleForm.resetFields()
      })
    }
  },
  mounted() {
    // 组件挂载完毕调用fetchRoleList()获取角色列表数据
    this.fetchRoleList()
  }
}
</script>

<template>
  <div class="role">
    <el-card class="layui-anim layui-anim-scale">
      <el-button type="primary" icon="el-icon-plus" @click="handleAddRole">添加角色</el-button>
      <el-table border stripe :data="roleList">
        <el-table-column label="角色名称" width="" align="center">
          <template #default="{row}">
            <!--编辑模式-->
            <el-input v-if="row.isEdit" v-model="row.editRow.name" v-focus></el-input>
            <!--查看模式-->
            <el-link v-else type="primary" :underline="false">{{ row.name }}</el-link>
          </template>
        </el-table-column>
        <el-table-column label="启用角色" width="" align="center">
          <template #default="{row}">
            <!--编辑模式-->
            <el-switch :key="row.isEdit" v-model="row.editRow.state" active-text="启用" inactive-text="关闭" :active-value="1" :inactive-value="0" active-color="#13ce66" inactive-color="#ff4949" v-if="row.isEdit"></el-switch>
            <!--查看模式-->
            <el-switch :key="row.isEdit" :value="row.state" active-text="启用角色" inactive-text="关闭角色" :active-value="1" :inactive-value="0" @change="changeState(row)" v-else></el-switch>
          </template>
        </el-table-column>
        <el-table-column label="角色描述" width="" align="center">
          <template #default="{row}">
            <!--编辑模式-->
            <el-input v-if="row.isEdit" v-model="row.editRow.description" v-focus></el-input>
            <!--查看模式-->
            <el-link v-else type="primary" :underline="false">{{ row.description }}</el-link>
          </template>
        </el-table-column>
        <el-table-column label="角色操作" width="" align="center">
          <template #default="{row}">
            <!--编辑模式-->
            <template v-if="row.isEdit">
              <el-button type="info" @click="handleUpdateCalcel(row)">取消</el-button>
              <el-button type="primary" @click="handleUpdateRole(row)">更新</el-button>
            </template>
            <!--查看模式-->
            <template v-else>
              <el-button type="success" icon="el-icon-s-flag" @click="handleAssignPrem(row)">分配权限</el-button>
              <el-button type="warning" icon="el-icon-edit" @click="handleEditRole(row)">编辑角色</el-button>
              <el-button type="danger" icon="el-icon-delete-solid" @click="handleDeleteRole(row)">删除角色</el-button>
            </template>
          </template>
        </el-table-column>
      </el-table>
      <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="pageParams.page" :page-sizes="[10, 20, 30, 40]" :page-size="pageParams.pagesize" layout="total, sizes, prev, pager, next, jumper" :total="pageParams.total" background></el-pagination>
    </el-card>
    <!--添加角色的弹层-->
    <el-dialog title="添加角色" :visible.sync="showRoleDialog" append-to-body :close-on-click-modal="false">
      <el-form label-width="120px" ref="roleForm" :model="roleForm" :rules="roleRules">
        <el-form-item label="角色名称" prop="name">
          <el-input placeholder="请输入角色名称" v-model.trim="roleForm.name"></el-input>
        </el-form-item>
        <el-form-item label="启用角色" prop="state">
          <el-switch active-text="启用" inactive-text="关闭" :active-value="1" :inactive-value="0" v-model="roleForm.state"></el-switch>
        </el-form-item>
        <el-form-item label="角色描述" prop="description">
          <el-input placeholder="请输入角色名称" type="textarea" resize="none" rows="4" v-model.trim="roleForm.description"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="danger" @click="handleCancel">取消</el-button>
          <el-button type="primary" @click="handleSubmit">确定</el-button>
        </el-form-item>
      </el-form>
    </el-dialog>
    <!--添加权限的弹层-->
    <PermissionList :isShowPermission.sync="isShowPermission" ref="permissionList"></PermissionList>
  </div>
</template>

<style scoped lang="scss">
.role {
  .el-card {
    margin-top: 10px;
  }

  .el-table {
    margin: 10px 0;
  }

  .el-pagination {
    display: flex;
    justify-content: center;
  }
}
</style>
